#pragma once

#include <map>
#include <functional>

#include "./eec/common.hpp"

namespace base {

typedef struct _tagAllocatorPlaceHolders {
} AlPH;

template<typename _K, typename _T, 
	typename _ARG1 = AlPH, typename _ARG2 = AlPH, typename _ARG3 = AlPH, typename _ARG4 = AlPH, typename _ARG5 = AlPH, typename _ARG6 = AlPH,
	typename _ARG7 = AlPH, typename _ARG8 = AlPH, typename _ARG9 = AlPH, typename _ARG10 = AlPH, typename _ARG11 = AlPH, typename _ARG12 = AlPH>
class HAllocator {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10,const _ARG11& _arg11,const _ARG12& _arg12)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
			const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10,const _ARG11& _arg11,const _ARG12& _arg12) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9,_arg10,_arg11,_arg12);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6,
typename _ARG7, typename _ARG8, typename _ARG9, typename _ARG10, typename _ARG11>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, _ARG11, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10,const _ARG11& _arg11)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10,const _ARG11& _arg11) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9,_arg10,_arg11);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6,
typename _ARG7, typename _ARG8, typename _ARG9, typename _ARG10>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9,const _ARG10& _arg10) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9,_arg10);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6,
typename _ARG7, typename _ARG8, typename _ARG9>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8,const _ARG9& _arg9) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8,_arg9);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6,
typename _ARG7, typename _ARG8>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
		const _ARG7& _arg7,const _ARG8& _arg8) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7,_arg8);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6,
typename _ARG7>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, AlPH, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6,
		const _ARG7& _arg7)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6,
		const _ARG7& _arg7) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6,_arg7);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, 
typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5, typename _ARG6>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5,const _ARG1& _arg6)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5, const _ARG6& _arg6) {
			_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
			if (list_.end() == l_itr_find) {
				return NULL;
			}
			return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5,_arg6);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};

template<typename _K, typename _T, typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4, typename _ARG5>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function< _T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4,const _ARG1& _arg5) > _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4, const _ARG5& _arg5) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1,_arg2,_arg3,_arg4,_arg5);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};


template<typename _K, typename _T, typename _ARG1, typename _ARG2, typename _ARG3, typename _ARG4>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, _ARG4, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3,const _ARG1& _arg4)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3, const _ARG4& _arg4) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1,_arg2,_arg3,_arg4);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};


template<typename _K, typename _T, typename _ARG1, typename _ARG2, typename _ARG3>
class HAllocator<_K, _T, _ARG1, _ARG2, _ARG3, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH>{

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1,const _ARG2& _arg2,const _ARG1& _arg3)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2, const _ARG3& _arg3) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1,_arg2,_arg3);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};


template<typename _K, typename _T, typename _ARG1, typename _ARG2>
class HAllocator<_K, _T, _ARG1, _ARG2, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH> {

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1, const _ARG2& _arg2)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1, const _ARG2& _arg2) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1,_arg2);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};


template<typename _K, typename _T, typename _ARG1>
class HAllocator<_K, _T, _ARG1, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH>{

public:
	typedef EEC_STD::function<_T* (const _ARG1& _arg1)> _Allocator;
	typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key, const _ARG1& _arg1) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second(_arg1);
	}
	bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
		if (list_.end() != l_itr_find) {
			return false;
		}
		return list_.insert(std::make_pair(_key, _allocator)).second;
	}

private:
	typename _AllocatorContainer list_;
};


template<typename _K, typename _T>
class HAllocator<_K, _T, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH, AlPH>{

public:
	typedef EEC_STD::function<_T* ()> _Allocator;
    typedef std::map<_K, _Allocator> _AllocatorContainer;

public:
	_T* alloc(const _K& _key) {
		_AllocatorContainer::iterator  l_itr_find = list_.find(_key);
		if (list_.end() == l_itr_find) {
			return NULL;
		}
		return l_itr_find->second();
	}
    bool set(const _K& _key, const _Allocator& _allocator) {
		_AllocatorContainer::iterator l_itr_find = list_.find(_key);
        if (list_.end() != l_itr_find) {
            return false;
        }
        return list_.insert(std::make_pair(_key, _allocator)).second;
    }

private:
    typename _AllocatorContainer list_;
};





} // namespace base

